home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 24
/
Amiga Format AFCD24 (Feb 1998, Issue 108).iso
/
-seriously_amiga-
/
shareware
/
programming
/
c
/
amivogl-mdev
/
drivers
/
sun.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-12
|
16KB
|
906 lines
/*
* Vogl/Vogle driver for Sun using sunview.
*
*/
/*
* define VOGLE for VOGLE library or leave blank for VOGL library
#define VOGLE 1
*/
#undef VOGLE
#include <stdio.h>
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <fcntl.h>
#include <errno.h>
#ifdef SUN_3_5
#define event_action event_id
#endif
#ifdef VOGLE
#include "vogle.h"
#else
#include "vogl.h"
#endif
#define CMAPSIZE 256
#define STDFONTDIR "/usr/lib/fonts/fixedwidthfonts/"
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define OP_WHITE (PIX_SRC | PIX_COLOR(7) | PIX_DONTCLIP)
#define OP_BLACK (PIX_SRC | PIX_COLOR(0) | PIX_DONTCLIP)
#define COL_WHITE 7
#define COL_BLACK 0
static Pixwin *pw_tmp, *pw;
#ifdef BASE_COL_SET
static Pixwin *pw0;
#endif
static Pixrect *backb;
static Pixfont *font_id;
static int wfd, blanket_win;
static int oldflags;
static int pwfd, h, w;
static int colour;
static Rect wrect;
static char use_sunview_canvas = 0;
#define DASHED 1
#define FATLINES 2
static unsigned char lineflags = 0;
static Pr_brush brush = {1};
static Pr_texture *t = (Pr_texture *)NULL;
static Pr_texture tex = {
(short *)NULL,
0,
{1, 1, 1, 0},
0,
};
/*
* default colour map
*/
static int colnum = 8;
static u_char red[CMAPSIZE] = {
0, 255, 0, 255, 0, 255, 0, 255, 0,
},
green[CMAPSIZE] = {
0, 0, 255, 255, 0, 0, 255, 255, 0,
},
blue[CMAPSIZE] = {
0, 0, 0, 0, 255, 255, 255, 255, 0,
};
/*
* redisplay
*
* redisplay the window.
*/
static void redisplay(void)
{
pw_damaged(pw);
pw_repairretained(pw);
pw_donedamaged(pw);
}
/*
* To be called from a resize procedure from withing sunview
*/
int vo_sunview_canvas_size(
int sw,
int sh)
{
w = sw;
h = sh;
vdevice.sizeX = vdevice.sizeY = MIN(h, w);
vdevice.sizeSx = w;
vdevice.sizeSy = h;
if (pw->pw_prretained) {
mem_destroy(pw->pw_prretained);
backb = pw->pw_prretained = mem_create(w, h, vdevice.depth);
}
}
/*
* vo_sunview_canvas
*
* Tells VOGLE/VOGL to use a supplied sunview pixwin
*/
int vo_sunview_canvas(
Canvas canvas,
int cw,
int ch)
{
pw = canvas_pixwin(canvas);
use_sunview_canvas = 1;
w = cw;
h = ch;
vdevice.sizeX = vdevice.sizeY = MIN(h, w);
vdevice.sizeSx = w;
vdevice.sizeSy = h;
vdevice.depth = pw->pw_pixrect->pr_depth;
if (!pw->pw_prretained) /* Make us retained */
backb = pw->pw_prretained = mem_create(w, h, vdevice.depth);
/*
* Set up the color map.
*/
if (vdevice.depth > 1) {
pw_setcmsname(pw, "vogle");
pw_putcolormap(pw, 0, colnum, red, green, blue);
}
wfd = (int)window_get(canvas, WIN_FD);
/*
* Set non-blocking input for window.
oldflags = fcntl(wfd, F_GETFL, 0);
if (fcntl(wfd, F_SETFL, FNDELAY) < 0) {
perror("F_SETFL");
exit(1);
}
*/
pw_batch_on(pw);
#ifndef VOGLE
vdevice.devname = "sun";
#endif
return(1);
}
/*
* SUN_init
*
* initialises drawing canvas to occupy current window
*/
int SUN_init(void)
{
int i, prefx, prefy, prefxs, prefys, bw;
char name[WIN_NAMESIZE];
Inputmask imk, imp;
int rootfd;
if (use_sunview_canvas)
return(1);
pw = (Pixwin *)NULL;
#ifdef BASE_COL_SET
pw0 = pw;
#endif
/*
* get the gfx win so we have some default sizes to use
*/
we_getgfxwindow(name);
pwfd = open(name, 2);
win_getrect(pwfd, &wrect);
/*
* Get the input masks of the base window...
*/
win_get_pick_mask(pwfd, &imp);
win_get_kbd_mask(pwfd, &imk);
/*
* get a new window (either going to be a blanket window or
* a window in it's own right)
*/
if ((wfd = win_getnewwindow()) == -1) {
fprintf(stderr, "No new windows!\n");
exit(1);
}
getprefposandsize(&prefx, &prefy, &prefxs, &prefys);
if (prefx > -1) {
wrect.r_left = prefx;
wrect.r_top = prefy;
}
if (prefxs > -1) {
wrect.r_width = prefxs;
wrect.r_height = prefys;
}
w = wrect.r_width;
h = wrect.r_height;
bw = 3;
if (prefx > -1 || prefxs > -1) {
/*
* Make room for a 3 pixel border
*/
if (wrect.r_left <= 2)
wrect.r_left = 0;
else
wrect.r_left -= bw;
if (wrect.r_top <= 2)
wrect.r_top = 0;
else
wrect.r_top -= bw;
wrect.r_width += 2 * bw;
wrect.r_height += 2 * bw;
win_setrect(wfd, &wrect);
/*
* get the parent (probably full screen window)
* so we can size our window to any size we like
* on the screen.
*/
we_getparentwindow(name);
rootfd = open(name, 2);
win_setlink(wfd, WL_PARENT, win_fdtonumber(rootfd));
win_setlink(wfd, WL_COVERED, WIN_NULLLINK);
win_insert(wfd);
wmgr_top(wfd, rootfd);
pw = pw_open(wfd);
#ifdef BASE_COL_SET
/*
* Get the pixrect for the window that we started in
* so we can set it's colourmap as well
*/
pw0 = pw_open(pwfd);
#endif
close(rootfd);
blanket_win = 0;
} else {
win_insertblanket(wfd, pwfd);
pw = pw_region(pw_open(wfd), 0, 0, w, h);
blanket_win = 1;
}
/*
* Set non-blocking input for window.
*/
oldflags = fcntl(wfd, F_GETFL, 0);
if (fcntl(wfd, F_SETFL, FNDELAY) < 0) {
perror("F_SETFL");
exit(1);
}
/*
* Setup the input masks for window.
*/
win_set_kbd_mask(wfd, &imk);
win_set_pick_mask(wfd, &imp);
vdevice.depth = pw->pw_pixrect->pr_depth;
/*
* Set up the color map.
*/
if (vdevice.depth > 1) {
pw_setcmsname(pw, "vogle");
pw_putcolormap(pw, 0, colnum, red, green, blue);
#ifdef BASE_COL_SET
if (pw0 != (Pixwin *)NULL) {
pw_setcmsname(pw0, "vogle");
pw_putcolormap(pw0, 0, colnum, red, green, blue);
}
#endif
}
if (prefx > -1 || prefxs > -1) {
/*
* Draw the border...
*/
int x0, y0, x1, y1;
x0 = y0 = 0;
x1 = wrect.r_width - 1;
y1 = 0;
pw_vector(pw, x0, y0, x1, y1, OP_WHITE, COL_WHITE);
pw_vector(pw, x0 + 2, y0 + 2, x1 - 2, y1 + 2, OP_WHITE, COL_WHITE);
pw_vector(pw, x0 + 1, y0 + 1, x1 - 1, y1 + 1, OP_BLACK, COL_BLACK);
x0 = x1;
y0 = y1;
x1 = x0;
y1 = wrect.r_height - 1;
pw_vector(pw, x0, y0, x1, y1, OP_WHITE, COL_WHITE);
pw_vector(pw, x0 - 2, y0 + 2, x1 - 2, y1 - 2, OP_WHITE, COL_WHITE);
pw_vector(pw, x0 - 1, y0 + 1, x1 - 1, y1 - 1, OP_BLACK, COL_BLACK);
x0 = x1;
y0 = y1;
x1 = 0;
y1 = wrect.r_height - 1;
pw_vector(pw, x0, y0, x1, y1, OP_WHITE, COL_WHITE);
pw_vector(pw, x0 - 2, y0 - 2, x1 + 2, y1 - 2, OP_WHITE, COL_WHITE);
pw_vector(pw, x0 - 1, y0 - 1, x1 + 1, y1 - 1, OP_BLACK, COL_BLACK);
x0 = x1;
y0 = y1;
x1 = 0;
y1 = 0;
pw_vector(pw, x0, y0, x1, y1, OP_WHITE, COL_WHITE);
pw_vector(pw, x0 + 2, y0 - 2, x1 + 2, y1 + 2, OP_WHITE, COL_WHITE);
pw_vector(pw, x0 + 1, y0 - 1, x1 + 1, y1 + 1, OP_BLACK, COL_BLACK);
pw_tmp = pw;
pw = pw_region(pw_tmp, 3, 3, w, h);
pw_close(pw_tmp);
}
backb = pw->pw_prretained = mem_create(w, h, vdevice.depth);
signal(SIGWINCH, redisplay);
/*
* Let VOGLE/VOGL know about the window size.
*/
vdevice.sizeX = vdevice.sizeY = MIN(w, h);
vdevice.sizeSx = w;
vdevice.sizeSy = h;
/*
* Set up batching.....(for speed and "pseudo" double buffering)
*/
pw_batch_on(pw);
return(1);
}
/*
* SUN_exit
*
* cleans up before returning the window to normal.
*/
int SUN_exit(void)
{
long nbytes;
int i;
Event event;
if (use_sunview_canvas)
return(1);
/*
* Flush all events for this window.
*
* While doing non-blocking input input_readevent returns -1 and
* errno == EWOULDBLOCK when everything has been read, so if
* errno != EWOULDBLOCK then something naughty happened...
*/
while (input_readevent(wfd, &event) >= 0)
;
if (errno != EWOULDBLOCK) {
perror("SUN_exit(flushing), input_readevent");
exit();
}
/*
* reset wfd to blocking input.
*/
if (fcntl(wfd, F_SETFL, oldflags) < 0) {
perror("oldflags, F_SETFL");
exit(1);
}
if (blanket_win)
win_removeblanket(wfd);
else
win_remove(wfd);
signal(SIGWINCH, SIG_DFL);
return(1);
}
/*
* SUN_draw
*
* draws a line from the current graphics position to (x, y).
*
* Note: (0, 0) is defined as the top left of the window on a sun (easy
* to forget).
*/
int SUN_draw(
int x,
int y)
{
if (!lineflags) /* If thin and solid */
pw_vector(pw, vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy, x, vdevice.sizeSy - y, PIX_SRC | PIX_COLOR(colour), colour);
else /* Fat and/or dashed */
pw_line(pw, vdevice.cpVx, vdevice.sizeSy - vdevice.cpVy, x, vdevice.sizeSy - y, &brush, t, PIX_SRC | PIX_COLOR(colour));
if (vdevice.sync)
pw_show(pw);
}
/*
* SUN_getkey
*
* grab a character from the keyboard.
*/
int SUN_getkey(void)
{
Event event;
pw_show(pw);
do {
while ((input_readevent(wfd, &event) < 0) && (errno == EWOULDBLOCK))
; /* Nothing to read - wait for something */
} while (!event_is_ascii(&event)); /* Wait for a key press */
return(event_action(&event));
}
/*
* SUN_checkkey
*
* Check if a keyboard key has been hit. If so return it.
*/
static Event *saved_event;
int SUN_checkkey(void)
{
static Event event;
if(saved_event == &event)
saved_event = NULL;
if (saved_event && event_is_ascii(saved_event)) {
Event *tmp = saved_event;
saved_event = NULL;
return(event_action(tmp));
}
saved_event = NULL;
if (input_readevent(wfd, &event) < 0) {
if (errno == EWOULDBLOCK) {
return(0);
} else {
perror("SUN_checkkey, input_readevent");
exit(1);
}
} else if (event_is_ascii(&event))
return(event_action(&event));
else
saved_event = &event;
return(0);
}
/*
* SUN_locator
*
* return the window location of the cursor, plus which mouse button,
* if any, is been pressed.
*/
int SUN_locator(
int *wx,
int *wy)
{
int but;
static Event event;
if (vdevice.sync)
pw_show(pw);
but = 0;
*wx = win_get_vuid_value(wfd, LOC_X_ABSOLUTE);
*wy = (int)vdevice.sizeSy - win_get_vuid_value(wfd, LOC_Y_ABSOLUTE);
/* This used to work under 4.0 but not longer ..... Maybe
* SUN don't want us to use sunview anymore?
*/
if (win_get_vuid_value(wfd, BUT(1)))
but |= 1;
if (win_get_vuid_value(wfd, BUT(2)))
but |= 2;
if (win_get_vuid_value(wfd, BUT(3)))
but |= 3;
if (use_sunview_canvas)
return(but);
if (saved_event == &event) /*Don't Re-use a previously rejected event*/
saved_event = NULL;
if (saved_event && event_is_button(saved_event) && event_is_down(saved_event)) {
if (event_action(saved_event) == MS_LEFT)
but |= 1;
if (event_action(saved_event) == MS_MIDDLE)
but |= 2;
if (event_action(saved_event) == MS_RIGHT)
but |= 4;
saved_event = NULL;
return(but);
}
if (input_readevent(wfd, &event) < 0) {
if (errno == EWOULDBLOCK) {
return(0);
} else {
perror("SUN_locator, input_readevent");
exit(1);
}
} else if (event_is_button(&event) && event_is_down(&event)) {
if (event_action(&event) == MS_LEFT)
but |= 1;
if (event_action(&event) == MS_MIDDLE)
but |= 2;
if (event_action(&event) == MS_RIGHT)
but |= 4;
} else
saved_event = &event;
return(but);
}
#ifdef VOGLE
/*
* SUN_clear
*
* Clear the screen to current colour
*/
int SUN_clear(void)
{
pw_writebackground(pw, 0, 0, w, h, PIX_SRC | PIX_COLOR(colour) | PIX_DONTCLIP);
if (vdevice.sync)
pw_show(pw);
}
#else
/*
* SUN_clear
*
* Clear the viewport to current colour
*/
int SUN_clear(void)
{
unsigned int vw = vdevice.maxVx - vdevice.minVx;
unsigned int vh = vdevice.maxVy - vdevice.minVy;
pw_writebackground(pw,
vdevice.minVx, vdevice.sizeSy - vdevice.maxVy,
vw, vh,
PIX_SRC | PIX_COLOR(colour) | PIX_DONTCLIP
);
if (vdevice.sync)
pw_show(pw);
}
#endif
/*
* SUN_color
*
* set the current drawing color index.
*/
int SUN_color(int ind)
{
colour = ind;
}
/*
* SUN_mapcolor
*
* change index i in the color map to the appropriate r, g, b, value.
*/
int SUN_mapcolor(
int i,
int r,
int g,
int b)
{
int j;
if (i >= 255 || vdevice.depth == 1)
return(-1);
if (i >= colnum)
colnum = i;
red[i] = r;
green[i] = g;
blue[i] = b;
red[255] = (u_char)~red[0];
green[255] = (u_char)~green[0];
blue[255] = (u_char)~blue[0];
pw_putcolormap(pw, 0, colnum, red, green, blue);
#ifdef BASE_COL_SET
pw_putcolormap(pw0, 0, colnum, red, green, blue);
#endif
}
/*
* SUN_font
*
* Set up a hardware font. Return 1 on success 0 otherwise.
*
*/
int SUN_font(char *fontfile)
{
char name[BUFSIZ];
if (font_id != (Pixfont *)NULL)
pf_close(font_id);
if ((font_id = pf_open(fontfile)) == NULL)
if (*fontfile != '/') {
strcpy(name, STDFONTDIR);
strcat(name, fontfile);
if ((font_id = pf_open(name)) == NULL)
return(0);
} else
return(0);
vdevice.hheight = font_id->pf_defaultsize.y;
vdevice.hwidth = font_id->pf_defaultsize.x;
return(1);
}
/*
* SUN_char
*
* outputs one char - is more complicated for other devices
*/
int SUN_char(char c)
{
char *s = " ";
s[0] = c;
pw_ttext(pw, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), PIX_SRC | PIX_COLOR(colour), font_id, s);
if (vdevice.sync)
pw_show(pw);
}
/*
* SUN_string
*
* Display a string at the current drawing position.
*/
int SUN_string(char s[])
{
pw_ttext(pw, vdevice.cpVx, (int)(vdevice.sizeSy - vdevice.cpVy), PIX_SRC | PIX_COLOR(colour), font_id, s);
if (vdevice.sync)
pw_show(pw);
}
/*
* SUN_fill
*
* fill a polygon
*/
int SUN_fill(
int n,
int x[],
int y[])
{
struct pr_pos vlist[128];
int i, npnts;
if (n > 128)
verror("vogle: more than 128 points in a polygon");
npnts = n;
for (i = 0; i < n; i++) {
vlist[i].x = x[i];
vlist[i].y = vdevice.sizeSy - y[i];
}
pw_polygon_2(pw, 0, 0, 1, &npnts, vlist, PIX_SRC | PIX_COLOR(colour) | PIX_DONTCLIP, (Pixwin *)NULL, 0, 0);
vdevice.cpVx = x[n-1];
vdevice.cpVy = y[n-1];
/*
if (vdevice.sync)
pw_show(pw);
*/
}
/*
* SUN_backb
*
* swap to memory only drawing (backbuffer) - a little slow but it
* works on everything.
*/
int SUN_backb(void)
{
/*
* Batching is already on....
*/
return(0);
}
/*
* SUN_swapb
*
* swap the front and back buffers.
*/
int SUN_swapb(void)
{
if (vdevice.inbackbuffer)
pw_show(pw);
return(0);
}
/*
* SUN_frontb
*
* draw in the front buffer
*/
int SUN_frontb(void)
{
/*
* Make it visible anyway....
*/
pw_show(pw);
}
/*
* SUN_sync
*
* Syncronise the display with what we thing has been output
*/
int SUN_sync(void)
{
pw_show(pw);
}
/*
* SUN_setls
*
* Set the line style....
*/
int SUN_setls(int lss)
{
unsigned ls = lss;
static short dashes[17];
int i, n, a, b, offset;
if (ls == 0xffff) {
lineflags &= ~DASHED;
t = (Pr_texture *)NULL;
return;
}
lineflags |= DASHED;
for (i = 0; i < 16; i++)
dashes[i] = 0;
for (i = 0; i < 16; i++) /* Over 16 bits */
if ((ls & (1 << i)))
break;
offset = i;
#define ON 1
#define OFF 0
a = b = OFF;
if (ls & (1 << 0))
a = b = ON;
n = 0;
for (i = 0; i < 16; i++) { /* Over 16 bits */
if (ls & (1 << i))
a = ON;
else
a = OFF;
if (a != b) {
b = a;
n++;
}
dashes[n]++;
}
n++;
dashes[n] = 0;
tex.pattern = &dashes[0];
tex.offset = offset;
t = &tex;
}
/*
* SUN_setlw
*
* Set the line style....
*/
int SUN_setlw(int lw)
{
if (lw > 1) {
lineflags |= FATLINES;
brush.width = lw;
} else
lineflags &= ~FATLINES;
}
/*
* the device entry
*/
static DevEntry sundev = {
"sun",
"screen.b.16",
"screen.b.12",
SUN_backb,
SUN_char,
SUN_checkkey,
SUN_clear,
SUN_color,
SUN_draw,
SUN_exit,
SUN_fill,
SUN_font,
SUN_frontb,
SUN_getkey,
SUN_init,
SUN_locator,
SUN_mapcolor,
#ifndef VOGLE
SUN_setls,
SUN_setlw,
#endif
SUN_string,
SUN_swapb,
SUN_sync
};
/*
* _SUN_devcpy
*
* copy the sun device into vdevice.dev.
*/
int _SUN_devcpy(void)
{
vdevice.dev = sundev;
}